/**
 * Copyright (c) 2018, wuxie All rights reserved.
 * qq:16349023,mail:16349023@qq.com
 * 未经许可禁止任何人通过任何渠道使用、修改源代码.
 * 项目名称 : wxcloud
 *
 * @version V1.0
 */
package cn.xo68.boot.auth.core.cookie;

import cn.xo68.core.security.Base64Utils;
import cn.xo68.core.util.JsonUtil;
import cn.xo68.core.util.StringTools;
import com.fasterxml.jackson.core.type.TypeReference;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

/**
 *  Cookie操作模板
 * @author wuxie
 * @date 2018/8/8 21:27
 *
 */
public class CookieTemplate<T extends Serializable> {

    private static final Logger logger= LoggerFactory.getLogger(CookieTemplate.class);

    protected Class<T> clazz;

    private final JsonUtil jsonUtil;
    private final SimpleCookie simpleCookie;
    /**
     * 是否转码
     */
    private boolean encode=false;

    public CookieTemplate(JsonUtil jsonUtil, String cookieName) {
        this.jsonUtil=jsonUtil;
        this.simpleCookie=new SimpleCookie(cookieName);
        this.simpleCookie.setPath("/");
        discernGenericClass();
    }

    public CookieTemplate(JsonUtil jsonUtil, SimpleCookie simpleCookie) {
        this.jsonUtil=jsonUtil;
        this.simpleCookie = simpleCookie;
        discernGenericClass();
    }

    /**
     * 识别泛型类型
     */
    private void discernGenericClass(){
        Type superClass = this.getClass().getGenericSuperclass();
        if(superClass instanceof ParameterizedType){
            Type arg = ((ParameterizedType) superClass).getActualTypeArguments()[0];
            if(arg instanceof Class){
                this.clazz = (Class<T>) arg;
            }else if(arg instanceof ParameterizedTypeImpl){
                this.clazz = (Class<T>) ((ParameterizedTypeImpl) arg).getRawType();
            }
        }else {
            this.clazz = (Class<T>) superClass;
        }

    }


    public boolean isEncode() {
        return encode;
    }

    public void setEncode(boolean encode) {
        this.encode = encode;
    }

    public String getCookieName(){
        return this.simpleCookie.getName();
    }

    public T getValue() {
        String base64Value= this.simpleCookie.getValue();
        if(StringTools.isEmpty(base64Value)){
            return null;
        }
        String strValue=base64Value;
        if(encode){
            strValue=Base64Utils.decodeToString(base64Value);
            if(StringTools.isEmpty(strValue)){
                return null;
            }

        }
        T value= jsonUtil.parse(strValue, clazz);
        return value;

    }

    public void setValue(T value) {
        String strValue= jsonUtil.toString(value,false);
        if(StringTools.isEmpty(strValue)){
            this.simpleCookie.setValue(StringTools.EMPTY);
            return;
        }
        if(encode){
            String base64Value=Base64Utils.encodeFromString(strValue);
            this.simpleCookie.setValue(base64Value);
        }else {
            this.simpleCookie.setValue(strValue);
        }

    }

    public String getComment() {
        return this.simpleCookie.getComment();
    }

    public void setComment(String comment) {
        this.simpleCookie.setComment(comment);
    }

    public String getDomain() {
        return this.simpleCookie.getDomain();
    }

    public void setDomain(String domain) {
        this.simpleCookie.setDomain(domain);
    }

    public String getPath() {
        return this.simpleCookie.getPath();
    }

    public void setPath(String path) {
        this.simpleCookie.setPath(path);
    }

    public int getMaxAge() {
        return this.simpleCookie.getMaxAge();
    }

    public void setMaxAge(int maxAge) {
        this.simpleCookie.setMaxAge(maxAge);
    }


    public boolean isSecure() {
        return this.simpleCookie.isSecure();
    }

    public void setSecure(boolean secure) {
        this.simpleCookie.setSecure(secure);
    }

    public boolean isHttpOnly() {
        return this.simpleCookie.isHttpOnly();
    }

    public void setHttpOnly(boolean httpOnly) {
        this.simpleCookie.setHttpOnly(httpOnly);
    }

    /**
     * 保存cookie
     * @param request
     * @param response
     */
    public void save(HttpServletRequest request, HttpServletResponse response){
        this.simpleCookie.saveTo(request,response);
    }

    /**
     * 加载cookie
     * @param request
     */
    public void load(HttpServletRequest request){
       String cookieValue= this.simpleCookie.readValue(request,null);
       this.simpleCookie.setValue(cookieValue);
    }

    public void delete(HttpServletRequest request, HttpServletResponse response){
        this.simpleCookie.removeFrom(request, response);
    }

}
